package com.example.oauth2demo.config;

import com.example.oauth2demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.ArrayList;
import java.util.List;

/**
 * description: 授权服务器配置类 <br>
 * date: 2021/5/21 23:50 <br>
 * author: xiehui <br>
 * version: 1.0 <br>
 * <p>
 * 参考链接：https://www.hangge.com/blog/cache/detail_2683.html
 */
@Configuration
@EnableAuthorizationServer
public class AuthorzationServer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    UserService userDetailsService;

    @Autowired
    AuthenticationManager authenticationManager;

    //@Autowired
    /**
     * 需要指定用哪个方式存储，信息如下：
     * Could not autowire. There is more than one bean of 'TokenStore' type.
     * Beans:
     * jwkTokenStore   (ResourceServerTokenServicesConfiguration.class)
     * jwtTokenStore   (AuthorizationServerTokenServicesConfiguration.class)
     * redisTokenStore   (RedisConfig.java)
     */
    //@Qualifier("redisTokenStore")
    //TokenStore tokenStore;

    // 使用 jwtTokenStore,存储方式
    @Autowired
    @Qualifier("jwtTokenStore")
    TokenStore tokenStore;

    // 对象信息转成jwt，颁发的AccessToken是jwt形式的
    @Autowired
    JwtAccessTokenConverter jwtAccessTokenConverter;

    // 添加自定义jwt内容
    @Autowired
    MyTokenEnhancer myTokenEnhancer;
    @Autowired
    MyTokenEnhancer2 myTokenEnhancer2;


    // 密码模式服务端点配置
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        // 存储redis
       /* endpoints
                // 令牌存储位置：默认是存储在内存中的
                .tokenStore(tokenStore)
                // 授权管理器
                .authenticationManager(authenticationManager)
                // 自定义登录逻辑
                .userDetailsService(userDetailsService);*/


        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> delegates = new ArrayList<>();
        delegates.add(myTokenEnhancer);
        delegates.add(myTokenEnhancer2);
        // 对象信息转成jwt
        delegates.add(jwtAccessTokenConverter);
        tokenEnhancerChain.setTokenEnhancers(delegates);
        endpoints
                // 令牌存储位置：默认是存储在内存中的
                .tokenStore(tokenStore)
                // 对象信息转成jwt格式
                .accessTokenConverter(jwtAccessTokenConverter)
                // 授权管理器
                .authenticationManager(authenticationManager)
                // 自定义登录逻辑
                .userDetailsService(userDetailsService)
                // 往jwt中添加自定义内容，添加增强信息链
                .tokenEnhancer(tokenEnhancerChain);
    }

    // 配置授权模式
    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.inMemory()
                // clientid
                .withClient("admin")
                //密码
                .secret(passwordEncoder.encode("112233"))
                // 重定向地址
                //.redirectUris("http://www.baidu.com")
                .redirectUris("http://127.0.0.1:8081/login")
                // 自动授权，不在跳转授权页面
                .autoApprove(true)
                // 授权范围
                .scopes("all")
                // 授权类型：有4种，授权码模式：authorization_code，简化模式：implicit，密码模式：password，客户端模式：client
                .authorizedGrantTypes("authorization_code", "password", "refresh_token")
                // 访问令牌失效时间默认是43200秒
                .accessTokenValiditySeconds(36000)
                // 刷新令牌失效时间
                .refreshTokenValiditySeconds(43000);
                 //.resourceIds("rid"); //配置资源id


    }


    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // Access表达式,isAuthenticated如果用户不是匿名登录的就返回true
        security.tokenKeyAccess("isAuthenticated()");
    }
}
